package com.onepunch.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;


// 作用于所有@RestController，捕获异常并返回JSON
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    // 1. 捕获自定义的业务异常（已知错误）
    @ExceptionHandler(BusinessException.class)
    public Result handBusinessException(BusinessException e) {
        LOG.error(e.getMessage(), e);
        return Result.error(e.getCode(),e.getMessage());
    }

    // 2. 捕获参数错误异常（如@RequestParam必填参数缺失）
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Result handleParameterMissing(Exception e) {
        LOG.error(e.getMessage(), e);
        return Result.error(1001, "参数错误：" + e.getMessage());
    }

    // 3. 捕获其他未知异常（如空指针、数据库错误等）
    @ExceptionHandler(Exception.class) // 所有未被上面捕获的异常，都会到这里
    public Result handleOtherException(Exception e) {
        // 生产环境中建议记录日志（e.printStackTrace()）
        // 将异常信息输出到控制台（包含堆栈跟踪）
        LOG.error(e.getMessage(), e);
        return Result.error(500, "服务器内部错误：" + e.getMessage());
    }
    /**
     * 捕获参数校验失败异常（@Valid注解触发）
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleMethodArgumentNotValid(MethodArgumentNotValidException e) {
        // 从异常中获取所有校验失败的信息
        StringBuilder errorMsg = new StringBuilder();
        e.getBindingResult().getFieldErrors().forEach(fieldError -> {
            // fieldError.getField()：获取校验失败的字段名
            // fieldError.getDefaultMessage()：获取校验失败的提示信息（即@NotBlank等注解的message）
            errorMsg.append(fieldError.getField()).append("：").append(fieldError.getDefaultMessage()).append("；");
        });

        // 返回统一的错误格式（code=400表示参数错误，msg拼接所有失败信息）
        return Result.error(400, "参数校验失败：" + errorMsg.toString());
    }

}
